package org.javaforever.gatescore.reports;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.javaforever.gatescore.core.FrontDomain;
import org.javaforever.gatescore.core.FrontDropdown;
import org.javaforever.gatescore.core.FrontField;
import org.javaforever.gatescore.core.FrontMethod;
import org.javaforever.gatescore.core.FrontVar;
import org.javaforever.gatescore.core.FrontVerb;
import org.javaforever.gatescore.core.Statement;
import org.javaforever.gatescore.core.StatementList;
import org.javaforever.gatescore.core.UtilsMethodGenerator;
import org.javaforever.gatescore.core.Writeable;
import org.javaforever.gatescore.core.WriteableUtil;
import org.javaforever.gatescore.reports.verb.ListActiveOption;
import org.javaforever.gatescore.reports.verb.ListActiveSumOption;
import org.javaforever.gatescore.reports.verb.Setup;
import org.javaforever.gatescore.reports.verb.Translate;
import org.javaforever.gatescore.utils.StringUtil;
import org.javaforever.gatescore.verb.ActivateAll;
import org.javaforever.gatescore.verb.ListActive;
import org.javaforever.gatescore.verb.SearchByFieldsByPage;
import org.javaforever.gatescore.verb.SoftDeleteAll;
import org.javaforever.gatescore.widgets.Layout;
import org.javaforever.gatescore.widgets.ToggleMenubar;
import org.javaforever.gatescore.widgets.ViewDialog;

public class EchartsGridReportLayout extends Layout{
	protected FrontDomain reportDomain;
	protected List<FrontField> xAxisFields;
	protected FrontField yName;
	protected EchartsDiagram diagram;
	protected DiagramDataControlGrid mainGrid;
	protected ToggleMenubar tmenubar;
	protected ViewDialog viewDialog;

	@Override
	public StatementList generateLayoutStatements() throws Exception{	
		List<Writeable> sList = new ArrayList<>();
		sList.add(new Statement(1000L,1,"<div>"));
		StatementList sl = diagram.generateWidgetStatements();
		sl.setIndent(2);
		sl.setSerial(2000L);
		
		StatementList tsl = tmenubar.generateWidgetStatements();
		tsl.setIndent(2);
		tsl.setSerial(3000L);
		
		StatementList sl2 = mainGrid.generateWidgetStatements();
		sl2.setIndent(2);
		sl2.setSerial(4000L);
		
		StatementList sl3 = viewDialog.generateWidgetStatements();
		sl3.setIndent(2);
		sl3.setSerial(5000L);	
		sList.add(sl);
		sList.add(tsl);
		sList.add(sl2);
		sList.add(sl3);
		sList.add(new Statement(6000L,1,"</div>"));	

		StatementList result =  WriteableUtil.merge(sList);
		result.setSerial(this.serial);
		return result;
	}

	@Override
	public StatementList generateLayoutScriptStatements() throws Exception{
		List<Writeable> sList = new ArrayList<>();
		long serial = 0L;
		sList.add(new Statement(serial+1000L,0,"import {"));		
		StringBuilder sb = new StringBuilder("search"+this.reportDomain.getCapFirstPlural()+"ByFieldsByPage, ");
		if (!(this.reportDomain instanceof org.javaforever.gatescore.core.FrontEnum)) {
			sb.append("softDeleteAll"+this.reportDomain.getCapFirstPlural()+", ");	
			sb.append("activateAll"+this.reportDomain.getCapFirstPlural()+", ");
		}
		ListActive la = new ListActive(this.reportDomain);
		sb.append(StringUtil.lowerFirst(la.getVerbName()));
		sList.add(new Statement(serial+2000L,1,sb.toString()));
		sList.add(new Statement(serial+3000L,0,"} from '@/api/"+this.reportDomain.getPlural().toLowerCase()+"'"));
		serial += 4000L;
		for (FrontField f:this.reportDomain.getAllFields()) {
			if (f instanceof FrontDropdown) {
				FrontDomain target = ((FrontDropdown)f).getTarget();
				ListActive tla = new ListActive(target);
				sList.add(new Statement(serial,0,"import {"));
				sList.add(new Statement(serial+1000L,1,StringUtil.lowerFirst(tla.getVerbName())));
				sList.add(new Statement(serial+2000L,0,"} from '@/api/"+target.getPlural().toLowerCase()+"'"));
				serial += 3000L;
			}
		}
		sList.add(new Statement(serial+1000L,0,"import { getToken } from '@/utils/auth'"));
		sList.add(new Statement(serial+2000L,0,"import pagevars from '@/pagevars'"));
		sList.add(new Statement(serial+3000L,0,"import Pagination from '@/components/Pagination' // Secondary package based on el-pagination"));
		sList.add(new Statement(serial+4000L,0,""));
		
		Set<FrontDomain> dpDomains = new TreeSet<FrontDomain>();
		FrontVar defaultForm = new FrontVar("defaultForm");
		FrontVar postForm = new FrontVar("postForm");
		FrontVar listQuery = new FrontVar("listQuery");
		FrontVar pagevars = new FrontVar("pagevars");
		FrontVar data = new FrontVar("data");	
		for (FrontField ff:this.reportDomain.getAllFieldsWithoutId()) {
			if (ff instanceof FrontDropdown) {
				FrontDropdown dp = (FrontDropdown) ff;
				dpDomains.add(dp.getTarget());
			}
		}
		serial += 5000L;
		
		StatementList sl = UtilsMethodGenerator.generateDefaultFormBlockStatements(this.reportDomain, defaultForm);
		sl.setSerial(serial+1000L);
		sList.add(sl);
		
		sList.add(new Statement(serial+2000L,0,"export function isBlank(val) {"));
		sList.add(new Statement(serial+3000L,1,"if (val === undefined || val === null || val === '') return true"));
		sList.add(new Statement(serial+4000L,1,"else return false"));
		sList.add(new Statement(serial+5000L,0,"}"));
		sList.add(new Statement(serial+6000L,0,""));
		sList.add(new Statement(serial+7000L,0,"export default {"));
		sList.add(new Statement(serial+8000L,1,"name: 'Echart',"));
		sList.add(new Statement(serial+9000L,1,"inject: ['reload'],"));
		sList.add(new Statement(serial+10600L,1,"components: {"));
		sList.add(new Statement(serial+11000L,2,"Pagination"));
		sList.add(new Statement(serial+12000L,1,"},"));
		
		sList.add(new Statement(serial+16000L,1,"filters: {"));
		serial += 17000L;
		for (FrontDomain d:dpDomains) {
			sl = UtilsMethodGenerator.generateDomainFilterStatements(d, pagevars);
			sl.setSerial(serial);
			sl.setIndent(1);
			sList.add(sl);
			serial += 1000L;
		}
		sList.add(new Statement(serial,1,"},"));
		
		sList.add(new Statement(serial+1000L,1,"data() {"));
		sList.add(new Statement(serial+2000L,2,"return {"));
		sList.add(new Statement(serial+3000L,3,"option: {},"));
		if (this.yName instanceof FrontDropdown) {
			FrontDomain target = ((FrontDropdown)this.yName).getTarget();
			sList.add(new Statement(serial+4000L,3,"active"+StringUtil.capFirst(target.getPlural())+": [],"));
		}
		sList.add(new Statement(serial+5000L,3,"active"+StringUtil.capFirst(this.reportDomain.getPlural())+": [],"));
		sList.add(new Statement(serial+6000L,3,"chartTypes: [{"));
		if (this.reportDomain.getLanguage().equalsIgnoreCase("english")) {
			sList.add(new Statement(serial+7000L,4,"value: 'line',"));
			sList.add(new Statement(serial+8000L,4,"label: 'Line'"));
			sList.add(new Statement(serial+9000L,3,"}, {"));
			sList.add(new Statement(serial+10000L,4,"value: 'bar',"));
			sList.add(new Statement(serial+11000L,4,"label: 'Bar'"));
			sList.add(new Statement(serial+12000L,3,"}, {"));
			sList.add(new Statement(serial+13000L,4,"value: 'pie',"));
			sList.add(new Statement(serial+14000L,4,"label: 'Pie'"));
			sList.add(new Statement(serial+15000L,3,"}],"));
			sList.add(new Statement(serial+16000L,3,"chartType: 'line',"));
			sList.add(new Statement(serial+17000L,3,"dataTypes: [{"));
			sList.add(new Statement(serial+18000L,4,"value: 'original',"));
			sList.add(new Statement(serial+19000L,4,"label: 'Original'"));
			sList.add(new Statement(serial+20000L,3,"}, {"));
			sList.add(new Statement(serial+21000L,4,"value: 'sum',"));
			sList.add(new Statement(serial+22000L,4,"label: 'Sum'"));
			sList.add(new Statement(serial+23000L,3,"}],"));
			sList.add(new Statement(serial+24000L,3,"dataType: 'original',"));
		}else {
			sList.add(new Statement(serial+7000L,4,"value: 'line',"));
			sList.add(new Statement(serial+8000L,4,"label: '折线图'"));
			sList.add(new Statement(serial+9000L,3,"}, {"));
			sList.add(new Statement(serial+10000L,4,"value: 'bar',"));
			sList.add(new Statement(serial+11000L,4,"label: '柱状图'"));
			sList.add(new Statement(serial+12000L,3,"}, {"));
			sList.add(new Statement(serial+13000L,4,"value: 'pie',"));
			sList.add(new Statement(serial+14000L,4,"label: '饼图'"));
			sList.add(new Statement(serial+15000L,3,"}],"));
			sList.add(new Statement(serial+16000L,3,"chartType: 'line',"));
			sList.add(new Statement(serial+17000L,3,"dataTypes: [{"));
			sList.add(new Statement(serial+18000L,4,"value: 'original',"));
			sList.add(new Statement(serial+19000L,4,"label: '原始数据'"));
			sList.add(new Statement(serial+20000L,3,"}, {"));
			sList.add(new Statement(serial+21000L,4,"value: 'sum',"));
			sList.add(new Statement(serial+22000L,4,"label: '累加数据'"));
			sList.add(new Statement(serial+23000L,3,"}],"));
			sList.add(new Statement(serial+24000L,3,"dataType: 'original',"));
		}
		serial += 25000L;
		sList.add(new Statement(serial,3,postForm.getVarName()+": Object.assign({}, "+defaultForm.getVarName()+"),"));
		sList.add(new Statement(serial+1000L,3,"list: [],"));
		sList.add(new Statement(serial+2000L,3,"selectList: [],"));
		sList.add(new Statement(serial+3000L,3,"selectRows: [],"));
		sList.add(new Statement(serial+4000L,3,"total: 0,"));
		sList.add(new Statement(serial+5000L,3,"listLoading: true,"));
		sList.add(new Statement(serial+6000L,3,"cellValue: null,"));
		sList.add(new Statement(serial+7000L,3,"viewDialogVisible: false,"));
		serial += 8000L;
		for (FrontField f: reportDomain.getFields()) {
			if (f.getFieldType()!=null&& f.getFieldType().getTypeName()!=null&&"image".equalsIgnoreCase(f.getFieldType().getTypeName())) {
				sList.add(new Statement(serial,3, f.getLowerFirstFieldName()+"ImageUrl: '',"));
				sList.add(new Statement(serial+1000L,3, f.getLowerFirstFieldName()+"File: '',"));
				serial += 2000L;
			}	
		}
		sList.add(new Statement(serial,3,"baseApi: process.env.BASE_API,"));
		sList.add(new Statement(serial+1000L,3,"token: getToken(),"));
		sList.add(new Statement(serial+2000L,3,"form: {},"));
		serial += 3000L;
		for (FrontDomain d: dpDomains) {
			sList.add(new Statement(serial,3,"active"+d.getCapFirstPlural()+": {},"));
			sList.add(new Statement(serial+1000L,3,"init"+d.getCapFirstDomainName()+"Store: "+pagevars.getVarName()+".init"+d.getCapFirstDomainName()+"Store,"));
			serial += 2000L;
		}
		sList.add(new Statement(serial,3,listQuery.getVarName()+": {"));
		sList.add(new Statement(serial+1000L,4,"page: 1,"));
		sList.add(new Statement(serial+2000L,4,"rows: 10"));
		sList.add(new Statement(serial+3000L,3,"}"));
		
		sList.add(new Statement(serial+4000L,2,"}"));
		sList.add(new Statement(serial+5000L,1,"},"));

		sl = UtilsMethodGenerator.generateCreatedBlockStatements(this.reportDomain, dpDomains);
		sl.setSerial(serial+5500L);
		sList.add(sl);
		
		sList.add(new Statement(serial+6000L,1,"mounted() {"));
		sList.add(new Statement(serial+7000L,2,"this.setup()"));
		sList.add(new Statement(serial+8000L,1,"},"));
		sList.add(new Statement(serial+9000L,1,"methods: {"));		
		
		StatementList sld = this.diagram.getSetup().generateControllerMethod().getMethodStatementList();
		sld.setSerial(serial+10000L);
		sld.setIndent(2);
		sList.add(sld);
		sList.add(new Statement(serial+11000L,0,""));
		
		for (FrontField f: reportDomain.getFields()) {
			if (f instanceof FrontDropdown) {
				FrontDomain target = ((FrontDropdown)f).getTarget();
				ListActive tla = new ListActive(target);
				StatementList tsl = tla.generateControllerMethod().getMethodStatementList();
				tsl.setSerial(serial+12000L);
				sList.add(tsl);
			}
		}
		StatementList osl = la.generateControllerMethod().getMethodStatementList();
		osl.setSerial(serial+13000L);
		sList.add(osl);

		serial += 15000L;
		for (FrontField f: reportDomain.getFields()) {
			if (f instanceof FrontDropdown) {
				FrontDomain target = ((FrontDropdown)f).getTarget();
				Translate tsl = new Translate(target);
				StatementList tsls = tsl.generateControllerMethod().getMethodStatementList();
				tsls.setSerial(serial);
				tsls.setIndent(2);
				sList.add(tsls);
				serial += 2000L;
			}
		}
		StatementList listoptionsl = this.diagram.getListOption().generateControllerMethod().getMethodStatementList();
		listoptionsl.setSerial(serial+1000L);
		listoptionsl.setIndent(2);
		sList.add(listoptionsl);
		
		StatementList listsumoptionsl = this.diagram.getListSumOption().generateControllerMethod().getMethodStatementList();
		listsumoptionsl.setSerial(serial+3000L);
		listsumoptionsl.setIndent(2);
		sList.add(listsumoptionsl);
		Set<FrontVerb> verbs = new TreeSet<>();
		ActivateAll ata = new ActivateAll(this.reportDomain);
		SoftDeleteAll sda = new SoftDeleteAll(this.reportDomain);
		SearchByFieldsByPage sfp = new SearchByFieldsByPage(this.reportDomain);
		verbs.add(ata);
		verbs.add(sda);
		verbs.add(sfp);
		
		serial += 5000L;
		for (FrontVerb fv: verbs ) {
			FrontMethod m = fv.generateControllerMethod();
			if (m!= null) {
				m.setSerial(serial);
				sList.add(m.getMethodStatementList());
				serial += 1000L;
			}
		}
		
		sl = UtilsMethodGenerator.generateBuildIdsStatements(this.reportDomain, data);
		sl.setSerial(serial+500L);
		sList.add(sl);	
		
		sl = UtilsMethodGenerator.generateBuildParamsStatements(this.reportDomain, listQuery, postForm);
		sl.setSerial(serial+1000L);
		sList.add(sl);
		
		sl = UtilsMethodGenerator.generateHandleSizeChangeMethodStatements(listQuery);
		sl.setSerial(serial+2000L);
		sList.add(sl);
		
		sl = UtilsMethodGenerator.generateHandleCurrentChangeMethodStatements(listQuery);
		sl.setSerial(serial+3000L);
		sList.add(sl);
		
		sl = UtilsMethodGenerator.generateHandleCheckedMethodStatements();
		sl.setSerial(serial+4000L);
		sList.add(sl);
		
		sl = UtilsMethodGenerator.generateHandleCheckedAllMethodStatements(this.reportDomain);
		sl.setSerial(serial+5000L);
		sList.add(sl);
		
		sl = UtilsMethodGenerator.generateSelectedHighlightMethodStatements();
		sl.setSerial(serial+6000L);
		sList.add(sl);
		
		sl = UtilsMethodGenerator.generateHandleCloseMethodStatements(this.reportDomain.getLanguage());
		sl.setSerial(serial+7000L);
		sList.add(sl);
		
		sl = UtilsMethodGenerator.generateShowViewDialogMethodStatements();
		sl.setSerial(serial+8000L);
		sList.add(sl);	
		
		sList.add(new Statement(serial+9000L,1,"}"));
		sList.add(new Statement(serial+10000L,0,"}"));
		StatementList result =  WriteableUtil.merge(sList);
		result.setSerial(this.serial);
		return result;
	}

	@Override
	public boolean parse() throws Exception{
		if (this.diagram == null) {
			ListActiveOption lao = new ListActiveOption(this.reportDomain,this.xAxisFields,this.yName);
			ListActiveSumOption laso = new ListActiveSumOption(this.reportDomain,this.xAxisFields,this.yName);
			Setup setup = new Setup(this.reportDomain,lao,laso);
			
			this.diagram = new EchartsDiagram();
			this.diagram.setDomain(this.reportDomain);
			this.diagram.setxAxisFields(this.xAxisFields);
			this.diagram.setyName(this.yName);
			this.diagram.setListOption(lao);
			this.diagram.setListSumOption(laso);
			this.diagram.setSetup(setup);
						
			this.mainGrid = new DiagramDataControlGrid("");
			this.mainGrid.setDomain(this.reportDomain);
			
			this.tmenubar = new ToggleMenubar(this.reportDomain);
			
			this.viewDialog = new ViewDialog(this.reportDomain,"");
		}
		return true;
	}

	public FrontDomain getReportDomain() {
		return reportDomain;
	}

	public void setReportDomain(FrontDomain reportDomain) {
		this.reportDomain = reportDomain;
	}

	public List<FrontField> getxAxisFields() {
		return xAxisFields;
	}

	public void setxAxisFields(List<FrontField> xAxisFields) {
		this.xAxisFields = xAxisFields;
	}

	public FrontField getyName() {
		return yName;
	}

	public void setyName(FrontField yName) {
		this.yName = yName;
	}

	public EchartsDiagram getDiagram() {
		return diagram;
	}

	public void setDiagram(EchartsDiagram diagram) {
		this.diagram = diagram;
	}

	@Override
	public StatementList generateStatements() throws Exception {
		List<Writeable> sList = new ArrayList<>();
		StatementList sl = this.generateLayoutStatements();
		StatementList sls = this.generateLayoutScriptStatements();
		sl.setSerial(2000L);
		sls.setSerial(5000L);
		
		sList.add(new Statement(1000L,0,"<template>"));
		sList.add(sl);	
		sList.add(new Statement(3000L,0,"</template>"));
		sList.add(new Statement(4000L,0,"<script>"));
		sList.add(sls);
		sList.add(new Statement(6000L,0,"</script>"));		
		return WriteableUtil.merge(sList);
	}

}
